// ProjectName: go-learn-demo
// PackageName: redisybxb
// Description:
// Author: hy.bai
// Date: 2025-08-25 星期一 10:45

package redisybxb

import (
	"fmt"
	"log/slog"
	"time"
)

func RedisSet() {
	var client, ctx, err = InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("Redis Init Error: %s", err.Error()))
	}
	// 第4个参数代表key的过期时间，0代表不会过期。
	statusCmd := client.Set(*ctx, "name-key", "hy.bai", 0) // *指针类型的变量：获取指针指向的值
	slog.Info(fmt.Sprintf("status: %s", statusCmd.Val()))
}

func RedisGet() {
	// RedisSet()
	var client, ctx, err = InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("redis init error: %s", err.Error()))
	}
	var key = "name-key"
	client.Set(*ctx, key, "hy.bai", 0)

	stringCmd := client.Get(*ctx, key)
	val := stringCmd.Val()
	slog.Info(fmt.Sprintf("结果类型是:%T, 值是:%v", val, val))

	// 为指定的key设置过期时间
	client.Expire(*ctx, key, 10*time.Second)

	// 获取指定key的过期时间
	ttl := client.TTL(*ctx, key)
	fmt.Println(ttl.Val())
}

func RedisGetSet() {
	var client, ctx, err = InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("redis init error: %s", err.Error()))
	}
	// 为指定key设置一个新值,并返回这个key的旧值.
	stringCmd := client.GetSet(*ctx, "name", "ybxb")
	val := stringCmd.Val()
	slog.Info(fmt.Sprintf("结果类型是:%T, 值是:%v", val, val))
}

func RedisSetNx() {
	var client, ctx, err = InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("redis init error: %s", err.Error()))
	}
	// 如果key不存在，则设置这个key的值,最后一个参数表示过期时间,0代表不会过期。
	// 不存在，保存成功，返回true，存在，保存失败，返回false
	boolCmd := client.SetNX(*ctx, "abcKey", "ybxb", 0)
	exists := boolCmd.Val()
	slog.Info(fmt.Sprintf("结果类型是:%T, 值是:%v", exists, exists))
}

func RedisMSet() {
	var client, ctx, err = InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("redis init error: %s", err.Error()))
	}
	// 批量设置Key,且不能设置过期时间
	statusCmd := client.MSet(*ctx, "key1", "value1", "key2", "value2", "key3", 1)
	val := statusCmd.Val()
	slog.Info(fmt.Sprintf("结果类型是:%T, 值是:%v", val, val))
}

func RedisMGet() {
	var client, ctx, err = InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("redis init error: %s", err.Error()))
	}
	// 批量设置Key,且不能设置过期时间
	sliceCmd := client.MGet(*ctx, "key1", "key2")
	val := sliceCmd.Val()
	for ind := range val { // val是空接口类型的切片接口
		slog.Info(fmt.Sprintf("结果类型是%T: %v", val, val[ind]))
	}
}

// Incr函数每次调用会加⼀,value必须为整数
func RedisIncr() {
	var client, ctx, err = InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("redis init error: %s", err.Error()))
	}
	// Incr函数每次调用会加⼀,value必须为整数
	intCmd := client.Incr(*ctx, "key3")
	val := intCmd.Val()
	slog.Info(fmt.Sprintf("结果类型是:%T, 值是:%v", val, val))
}

func RedisIncrBy() {
	var client, ctx, err = InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("redis init error: %s", err.Error()))
	}
	// Incr函数每次调用会增加指定的步长值(第3个参数是步长值),value必须为整数
	intCmd := client.IncrBy(*ctx, "key3", 3)
	val := intCmd.Val()
	slog.Info(fmt.Sprintf("结果类型是:%T, 值是:%v", val, val))
}

func RedisIncrByFloat() {
	var client, ctx, err = InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("redis init error: %s", err.Error()))
	}
	// Incr函数每次调用会增加指定的步长值(第3个参数是步长值),value必须为整数。跟IncrBy的区别是累加的是浮点数
	intCmd := client.IncrByFloat(*ctx, "key3", 1.8)
	val := intCmd.Val()
	slog.Info(fmt.Sprintf("结果类型是:%T, 值是:%v", val, val))
}

// 以上是值的增加，而Decr、DecrBy方法的作用是相反的

func RedisDel() {
	var client, ctx, err = InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("redis init error: %s", err.Error()))
	}
	// 根据key值删除指定的数据,可以删除多个
	intCmd := client.Del(*ctx, "key1", "key2")
	val := intCmd.Val()
	slog.Info(fmt.Sprintf("结果类型是:%T, 值是:%v", val, val))
}

// 为指定的key设置过期时间
func RedisExpire() {
	var client, ctx, err = InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("redis init error: %s", err.Error()))
	}
	// 根据key值设置过期时间
	boolCmd := client.Expire(*ctx, "abcKey", time.Second*10)
	val := boolCmd.Val()
	slog.Info(fmt.Sprintf("结果类型是:%T, 值是:%v", val, val))
}

// 当前go文件的调用入口
func TestBasic() {
	RedisGet()
}
